const A_INSTRUCTION = 0;
const C_INSTRUCTION = 1;
const L_INSTRUCTION = 2;

class Parser {
  constructor(littleIO) {
    this.littleIO = littleIO;
    this.currentInstruction = null;
    this._symbol = '';
    this._dest = '';
    this._comp = '';
    this._jump = '';
  }

  hasMoreLines() {
    return this.littleIO.hasMoreLines();
  }

  advance() {
    this.currentInstruction = this.littleIO.advance();
    if (!this.currentInstruction) return;

    if (this.instructionType() === A_INSTRUCTION) {
      this._symbol = this.currentInstruction.slice(1);
    } else if (this.instructionType() === L_INSTRUCTION) {
      this._symbol = this.currentInstruction.slice(1, -1);
    } else {
      if (this.currentInstruction.includes('=')) {
        const [dest, rest] = this.currentInstruction.split('=');
        const [comp, jump] = rest.split(';');
        this._dest = dest;
        this._comp = comp;
        this._jump = jump;
      } else if (this.currentInstruction.includes(';')) {
        const [comp, jump] = this.currentInstruction.split(';');
        this._dest = null;
        this._comp = comp;
        this._jump = jump;
      } else {
        this._dest = null;
        this._comp = this.currentInstruction;
        this._jump = null;
      }
    }
    return this.currentInstruction;
  }

  instructionType() {
    if (this.currentInstruction.startsWith('@')) {
      return A_INSTRUCTION;
    }
    if (this.currentInstruction.startsWith('(')) {
      return L_INSTRUCTION;
    }
    return C_INSTRUCTION;
  }

  isAInstruction() {
    return this.instructionType() === A_INSTRUCTION;
  }

  isCInstruction() {
    return this.instructionType() === C_INSTRUCTION;
  }

  isLInstruction() {
    return this.instructionType() === L_INSTRUCTION;
  }

  symbol() {
    return this._symbol;
  }

  dest() {
    return this._dest || 'null';
  }

  comp() {
    return this._comp || 'null';
  }

  jump() {
    return this._jump || 'null';
  }
}

module.exports.Parser = Parser;
